home *** CD-ROM | disk | FTP | other *** search
/ Introduction to 3D Game …ogramming with DirectX 12 / Introduction-to-3D-Game-Programming-with-DirectX-12.ISO / Code.Textures / Chapter 20 Shadow Mapping / Shadows / ShadowMapApp.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2016-03-02  |  57.3 KB  |  1,492 lines

  1. //***************************************************************************************
  2. // ShadowMapApp.cpp by Frank Luna (C) 2015 All Rights Reserved.
  3. //***************************************************************************************
  4.  
  5. #include "../../Common/d3dApp.h"
  6. #include "../../Common/MathHelper.h"
  7. #include "../../Common/UploadBuffer.h"
  8. #include "../../Common/GeometryGenerator.h"
  9. #include "../../Common/Camera.h"
  10. #include "FrameResource.h"
  11. #include "ShadowMap.h"
  12.  
  13. using Microsoft::WRL::ComPtr;
  14. using namespace DirectX;
  15. using namespace DirectX::PackedVector;
  16.  
  17. const int gNumFrameResources = 3;
  18.  
  19. // Lightweight structure stores parameters to draw a shape.  This will
  20. // vary from app-to-app.
  21. struct RenderItem
  22. {
  23.     RenderItem() = default;
  24.     RenderItem(const RenderItem& rhs) = delete;
  25.  
  26.     // World matrix of the shape that describes the object's local space
  27.     // relative to the world space, which defines the position, orientation,
  28.     // and scale of the object in the world.
  29.     XMFLOAT4X4 World = MathHelper::Identity4x4();
  30.  
  31.     XMFLOAT4X4 TexTransform = MathHelper::Identity4x4();
  32.  
  33.     // Dirty flag indicating the object data has changed and we need to update the constant buffer.
  34.     // Because we have an object cbuffer for each FrameResource, we have to apply the
  35.     // update to each FrameResource.  Thus, when we modify obect data we should set 
  36.     // NumFramesDirty = gNumFrameResources so that each frame resource gets the update.
  37.     int NumFramesDirty = gNumFrameResources;
  38.  
  39.     // Index into GPU constant buffer corresponding to the ObjectCB for this render item.
  40.     UINT ObjCBIndex = -1;
  41.  
  42.     Material* Mat = nullptr;
  43.     MeshGeometry* Geo = nullptr;
  44.  
  45.     // Primitive topology.
  46.     D3D12_PRIMITIVE_TOPOLOGY PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  47.  
  48.     // DrawIndexedInstanced parameters.
  49.     UINT IndexCount = 0;
  50.     UINT StartIndexLocation = 0;
  51.     int BaseVertexLocation = 0;
  52. };
  53.  
  54. enum class RenderLayer : int
  55. {
  56.     Opaque = 0,
  57.     Debug,
  58.     Sky,
  59.     Count
  60. };
  61.  
  62. class ShadowMapApp : public D3DApp
  63. {
  64. public:
  65.     ShadowMapApp(HINSTANCE hInstance);
  66.     ShadowMapApp(const ShadowMapApp& rhs) = delete;
  67.     ShadowMapApp& operator=(const ShadowMapApp& rhs) = delete;
  68.     ~ShadowMapApp();
  69.  
  70.     virtual bool Initialize()override;
  71.  
  72. private:
  73.     virtual void CreateRtvAndDsvDescriptorHeaps()override;
  74.     virtual void OnResize()override;
  75.     virtual void Update(const GameTimer& gt)override;
  76.     virtual void Draw(const GameTimer& gt)override;
  77.  
  78.     virtual void OnMouseDown(WPARAM btnState, int x, int y)override;
  79.     virtual void OnMouseUp(WPARAM btnState, int x, int y)override;
  80.     virtual void OnMouseMove(WPARAM btnState, int x, int y)override;
  81.  
  82.     void OnKeyboardInput(const GameTimer& gt);
  83.     void AnimateMaterials(const GameTimer& gt);
  84.     void UpdateObjectCBs(const GameTimer& gt);
  85.     void UpdateMaterialBuffer(const GameTimer& gt);
  86.     void UpdateShadowTransform(const GameTimer& gt);
  87.     void UpdateMainPassCB(const GameTimer& gt);
  88.     void UpdateShadowPassCB(const GameTimer& gt);
  89.  
  90.     void LoadTextures();
  91.     void BuildRootSignature();
  92.     void BuildDescriptorHeaps();
  93.     void BuildShadersAndInputLayout();
  94.     void BuildShapeGeometry();
  95.     void BuildSkullGeometry();
  96.     void BuildPSOs();
  97.     void BuildFrameResources();
  98.     void BuildMaterials();
  99.     void BuildRenderItems();
  100.     void DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems);
  101.     void DrawSceneToShadowMap();
  102.  
  103.     std::array<const CD3DX12_STATIC_SAMPLER_DESC, 7> GetStaticSamplers();
  104.  
  105. private:
  106.  
  107.     std::vector<std::unique_ptr<FrameResource>> mFrameResources;
  108.     FrameResource* mCurrFrameResource = nullptr;
  109.     int mCurrFrameResourceIndex = 0;
  110.  
  111.     ComPtr<ID3D12RootSignature> mRootSignature = nullptr;
  112.  
  113.     ComPtr<ID3D12DescriptorHeap> mSrvDescriptorHeap = nullptr;
  114.  
  115.     std::unordered_map<std::string, std::unique_ptr<MeshGeometry>> mGeometries;
  116.     std::unordered_map<std::string, std::unique_ptr<Material>> mMaterials;
  117.     std::unordered_map<std::string, std::unique_ptr<Texture>> mTextures;
  118.     std::unordered_map<std::string, ComPtr<ID3DBlob>> mShaders;
  119.     std::unordered_map<std::string, ComPtr<ID3D12PipelineState>> mPSOs;
  120.  
  121.     std::vector<D3D12_INPUT_ELEMENT_DESC> mInputLayout;
  122.  
  123.     // List of all the render items.
  124.     std::vector<std::unique_ptr<RenderItem>> mAllRitems;
  125.  
  126.     // Render items divided by PSO.
  127.     std::vector<RenderItem*> mRitemLayer[(int)RenderLayer::Count];
  128.  
  129.     UINT mSkyTexHeapIndex = 0;
  130.     UINT mShadowMapHeapIndex = 0;
  131.  
  132.     UINT mNullCubeSrvIndex = 0;
  133.     UINT mNullTexSrvIndex = 0;
  134.  
  135.     CD3DX12_GPU_DESCRIPTOR_HANDLE mNullSrv;
  136.  
  137.     PassConstants mMainPassCB;  // index 0 of pass cbuffer.
  138.     PassConstants mShadowPassCB;// index 1 of pass cbuffer.
  139.  
  140.     Camera mCamera;
  141.  
  142.     std::unique_ptr<ShadowMap> mShadowMap;
  143.  
  144.     DirectX::BoundingSphere mSceneBounds;
  145.  
  146.     float mLightNearZ = 0.0f;
  147.     float mLightFarZ = 0.0f;
  148.     XMFLOAT3 mLightPosW;
  149.     XMFLOAT4X4 mLightView = MathHelper::Identity4x4();
  150.     XMFLOAT4X4 mLightProj = MathHelper::Identity4x4();
  151.     XMFLOAT4X4 mShadowTransform = MathHelper::Identity4x4();
  152.  
  153.     float mLightRotationAngle = 0.0f;
  154.     XMFLOAT3 mBaseLightDirections[3] = {
  155.         XMFLOAT3(0.57735f, -0.57735f, 0.57735f),
  156.         XMFLOAT3(-0.57735f, -0.57735f, 0.57735f),
  157.         XMFLOAT3(0.0f, -0.707f, -0.707f)
  158.     };
  159.     XMFLOAT3 mRotatedLightDirections[3];
  160.  
  161.     POINT mLastMousePos;
  162. };
  163.  
  164. int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE prevInstance,
  165.     PSTR cmdLine, int showCmd)
  166. {
  167.     // Enable run-time memory check for debug builds.
  168. #if defined(DEBUG) | defined(_DEBUG)
  169.     _CrtSetDbgFlag(_CRTDBG_ALLOC_MEM_DF | _CRTDBG_LEAK_CHECK_DF);
  170. #endif
  171.  
  172.     try
  173.     {
  174.         ShadowMapApp theApp(hInstance);
  175.         if(!theApp.Initialize())
  176.             return 0;
  177.  
  178.         return theApp.Run();
  179.     }
  180.     catch(DxException& e)
  181.     {
  182.         MessageBox(nullptr, e.ToString().c_str(), L"HR Failed", MB_OK);
  183.         return 0;
  184.     }
  185. }
  186.  
  187. ShadowMapApp::ShadowMapApp(HINSTANCE hInstance)
  188.     : D3DApp(hInstance)
  189. {
  190.     // Estimate the scene bounding sphere manually since we know how the scene was constructed.
  191.     // The grid is the "widest object" with a width of 20 and depth of 30.0f, and centered at
  192.     // the world space origin.  In general, you need to loop over every world space vertex
  193.     // position and compute the bounding sphere.
  194.     mSceneBounds.Center = XMFLOAT3(0.0f, 0.0f, 0.0f);
  195.     mSceneBounds.Radius = sqrtf(10.0f*10.0f + 15.0f*15.0f);
  196. }
  197.  
  198. ShadowMapApp::~ShadowMapApp()
  199. {
  200.     if(md3dDevice != nullptr)
  201.         FlushCommandQueue();
  202. }
  203.  
  204. bool ShadowMapApp::Initialize()
  205. {
  206.     if(!D3DApp::Initialize())
  207.         return false;
  208.  
  209.     // Reset the command list to prep for initialization commands.
  210.     ThrowIfFailed(mCommandList->Reset(mDirectCmdListAlloc.Get(), nullptr));
  211.  
  212.     mCamera.SetPosition(0.0f, 2.0f, -15.0f);
  213.  
  214.     mShadowMap = std::make_unique<ShadowMap>(
  215.         md3dDevice.Get(), 2048, 2048);
  216.  
  217.     LoadTextures();
  218.     BuildRootSignature();
  219.     BuildDescriptorHeaps();
  220.     BuildShadersAndInputLayout();
  221.     BuildShapeGeometry();
  222.     BuildSkullGeometry();
  223.     BuildMaterials();
  224.     BuildRenderItems();
  225.     BuildFrameResources();
  226.     BuildPSOs();
  227.  
  228.     // Execute the initialization commands.
  229.     ThrowIfFailed(mCommandList->Close());
  230.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  231.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  232.  
  233.     // Wait until initialization is complete.
  234.     FlushCommandQueue();
  235.  
  236.     return true;
  237. }
  238.  
  239. void ShadowMapApp::CreateRtvAndDsvDescriptorHeaps()
  240. {
  241.     // Add +6 RTV for cube render target.
  242.     D3D12_DESCRIPTOR_HEAP_DESC rtvHeapDesc;
  243.     rtvHeapDesc.NumDescriptors = SwapChainBufferCount;
  244.     rtvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_RTV;
  245.     rtvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  246.     rtvHeapDesc.NodeMask = 0;
  247.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
  248.         &rtvHeapDesc, IID_PPV_ARGS(mRtvHeap.GetAddressOf())));
  249.  
  250.     // Add +1 DSV for shadow map.
  251.     D3D12_DESCRIPTOR_HEAP_DESC dsvHeapDesc;
  252.     dsvHeapDesc.NumDescriptors = 2;
  253.     dsvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_DSV;
  254.     dsvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_NONE;
  255.     dsvHeapDesc.NodeMask = 0;
  256.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(
  257.         &dsvHeapDesc, IID_PPV_ARGS(mDsvHeap.GetAddressOf())));
  258. }
  259.  
  260. void ShadowMapApp::OnResize()
  261. {
  262.     D3DApp::OnResize();
  263.  
  264.     mCamera.SetLens(0.25f*MathHelper::Pi, AspectRatio(), 1.0f, 1000.0f);
  265. }
  266.  
  267. void ShadowMapApp::Update(const GameTimer& gt)
  268. {
  269.     OnKeyboardInput(gt);
  270.  
  271.     // Cycle through the circular frame resource array.
  272.     mCurrFrameResourceIndex = (mCurrFrameResourceIndex + 1) % gNumFrameResources;
  273.     mCurrFrameResource = mFrameResources[mCurrFrameResourceIndex].get();
  274.  
  275.     // Has the GPU finished processing the commands of the current frame resource?
  276.     // If not, wait until the GPU has completed commands up to this fence point.
  277.     if(mCurrFrameResource->Fence != 0 && mFence->GetCompletedValue() < mCurrFrameResource->Fence)
  278.     {
  279.         HANDLE eventHandle = CreateEventEx(nullptr, false, false, EVENT_ALL_ACCESS);
  280.         ThrowIfFailed(mFence->SetEventOnCompletion(mCurrFrameResource->Fence, eventHandle));
  281.         WaitForSingleObject(eventHandle, INFINITE);
  282.         CloseHandle(eventHandle);
  283.     }
  284.  
  285.     //
  286.     // Animate the lights (and hence shadows).
  287.     //
  288.  
  289.     mLightRotationAngle += 0.1f*gt.DeltaTime();
  290.  
  291.     XMMATRIX R = XMMatrixRotationY(mLightRotationAngle);
  292.     for(int i = 0; i < 3; ++i)
  293.     {
  294.         XMVECTOR lightDir = XMLoadFloat3(&mBaseLightDirections[i]);
  295.         lightDir = XMVector3TransformNormal(lightDir, R);
  296.         XMStoreFloat3(&mRotatedLightDirections[i], lightDir);
  297.     }
  298.  
  299.     AnimateMaterials(gt);
  300.     UpdateObjectCBs(gt);
  301.     UpdateMaterialBuffer(gt);
  302.     UpdateShadowTransform(gt);
  303.     UpdateMainPassCB(gt);
  304.     UpdateShadowPassCB(gt);
  305. }
  306.  
  307. void ShadowMapApp::Draw(const GameTimer& gt)
  308. {
  309.     auto cmdListAlloc = mCurrFrameResource->CmdListAlloc;
  310.  
  311.     // Reuse the memory associated with command recording.
  312.     // We can only reset when the associated command lists have finished execution on the GPU.
  313.     ThrowIfFailed(cmdListAlloc->Reset());
  314.  
  315.     // A command list can be reset after it has been added to the command queue via ExecuteCommandList.
  316.     // Reusing the command list reuses memory.
  317.     ThrowIfFailed(mCommandList->Reset(cmdListAlloc.Get(), mPSOs["opaque"].Get()));
  318.  
  319.     ID3D12DescriptorHeap* descriptorHeaps[] = { mSrvDescriptorHeap.Get() };
  320.     mCommandList->SetDescriptorHeaps(_countof(descriptorHeaps), descriptorHeaps);
  321.  
  322.     mCommandList->SetGraphicsRootSignature(mRootSignature.Get());
  323.  
  324.     // Bind all the materials used in this scene.  For structured buffers, we can bypass the heap and 
  325.     // set as a root descriptor.
  326.     auto matBuffer = mCurrFrameResource->MaterialBuffer->Resource();
  327.     mCommandList->SetGraphicsRootShaderResourceView(2, matBuffer->GetGPUVirtualAddress());
  328.  
  329.     // Bind null SRV for shadow map pass.
  330.     mCommandList->SetGraphicsRootDescriptorTable(3, mNullSrv);     
  331.  
  332.     // Bind all the textures used in this scene.  Observe
  333.     // that we only have to specify the first descriptor in the table.  
  334.     // The root signature knows how many descriptors are expected in the table.
  335.     mCommandList->SetGraphicsRootDescriptorTable(4, mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  336.  
  337.     DrawSceneToShadowMap();
  338.  
  339.     mCommandList->RSSetViewports(1, &mScreenViewport);
  340.     mCommandList->RSSetScissorRects(1, &mScissorRect);
  341.  
  342.     // Indicate a state transition on the resource usage.
  343.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  344.         D3D12_RESOURCE_STATE_PRESENT, D3D12_RESOURCE_STATE_RENDER_TARGET));
  345.  
  346.     // Clear the back buffer and depth buffer.
  347.     mCommandList->ClearRenderTargetView(CurrentBackBufferView(), Colors::LightSteelBlue, 0, nullptr);
  348.     mCommandList->ClearDepthStencilView(DepthStencilView(), D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  349.  
  350.     // Specify the buffers we are going to render to.
  351.     mCommandList->OMSetRenderTargets(1, &CurrentBackBufferView(), true, &DepthStencilView());
  352.  
  353.     auto passCB = mCurrFrameResource->PassCB->Resource();
  354.     mCommandList->SetGraphicsRootConstantBufferView(1, passCB->GetGPUVirtualAddress());
  355.  
  356.     // Bind the sky cube map.  For our demos, we just use one "world" cube map representing the environment
  357.     // from far away, so all objects will use the same cube map and we only need to set it once per-frame.  
  358.     // If we wanted to use "local" cube maps, we would have to change them per-object, or dynamically
  359.     // index into an array of cube maps.
  360.  
  361.     CD3DX12_GPU_DESCRIPTOR_HANDLE skyTexDescriptor(mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart());
  362.     skyTexDescriptor.Offset(mSkyTexHeapIndex, mCbvSrvUavDescriptorSize);
  363.     mCommandList->SetGraphicsRootDescriptorTable(3, skyTexDescriptor);
  364.  
  365.     mCommandList->SetPipelineState(mPSOs["opaque"].Get());
  366.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  367.  
  368.     mCommandList->SetPipelineState(mPSOs["debug"].Get());
  369.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Debug]);
  370.  
  371.     mCommandList->SetPipelineState(mPSOs["sky"].Get());
  372.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Sky]);
  373.  
  374.     // Indicate a state transition on the resource usage.
  375.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(CurrentBackBuffer(),
  376.         D3D12_RESOURCE_STATE_RENDER_TARGET, D3D12_RESOURCE_STATE_PRESENT));
  377.  
  378.     // Done recording commands.
  379.     ThrowIfFailed(mCommandList->Close());
  380.  
  381.     // Add the command list to the queue for execution.
  382.     ID3D12CommandList* cmdsLists[] = { mCommandList.Get() };
  383.     mCommandQueue->ExecuteCommandLists(_countof(cmdsLists), cmdsLists);
  384.  
  385.     // Swap the back and front buffers
  386.     ThrowIfFailed(mSwapChain->Present(0, 0));
  387.     mCurrBackBuffer = (mCurrBackBuffer + 1) % SwapChainBufferCount;
  388.  
  389.     // Advance the fence value to mark commands up to this fence point.
  390.     mCurrFrameResource->Fence = ++mCurrentFence;
  391.  
  392.     // Add an instruction to the command queue to set a new fence point. 
  393.     // Because we are on the GPU timeline, the new fence point won't be 
  394.     // set until the GPU finishes processing all the commands prior to this Signal().
  395.     mCommandQueue->Signal(mFence.Get(), mCurrentFence);
  396. }
  397.  
  398. void ShadowMapApp::OnMouseDown(WPARAM btnState, int x, int y)
  399. {
  400.     mLastMousePos.x = x;
  401.     mLastMousePos.y = y;
  402.  
  403.     SetCapture(mhMainWnd);
  404. }
  405.  
  406. void ShadowMapApp::OnMouseUp(WPARAM btnState, int x, int y)
  407. {
  408.     ReleaseCapture();
  409. }
  410.  
  411. void ShadowMapApp::OnMouseMove(WPARAM btnState, int x, int y)
  412. {
  413.     if((btnState & MK_LBUTTON) != 0)
  414.     {
  415.         // Make each pixel correspond to a quarter of a degree.
  416.         float dx = XMConvertToRadians(0.25f*static_cast<float>(x - mLastMousePos.x));
  417.         float dy = XMConvertToRadians(0.25f*static_cast<float>(y - mLastMousePos.y));
  418.  
  419.         mCamera.Pitch(dy);
  420.         mCamera.RotateY(dx);
  421.     }
  422.  
  423.     mLastMousePos.x = x;
  424.     mLastMousePos.y = y;
  425. }
  426.  
  427. void ShadowMapApp::OnKeyboardInput(const GameTimer& gt)
  428. {
  429.     const float dt = gt.DeltaTime();
  430.  
  431.     if(GetAsyncKeyState('W') & 0x8000)
  432.         mCamera.Walk(10.0f*dt);
  433.  
  434.     if(GetAsyncKeyState('S') & 0x8000)
  435.         mCamera.Walk(-10.0f*dt);
  436.  
  437.     if(GetAsyncKeyState('A') & 0x8000)
  438.         mCamera.Strafe(-10.0f*dt);
  439.  
  440.     if(GetAsyncKeyState('D') & 0x8000)
  441.         mCamera.Strafe(10.0f*dt);
  442.  
  443.     mCamera.UpdateViewMatrix();
  444. }
  445.  
  446. void ShadowMapApp::AnimateMaterials(const GameTimer& gt)
  447. {
  448.     
  449. }
  450.  
  451. void ShadowMapApp::UpdateObjectCBs(const GameTimer& gt)
  452. {
  453.     auto currObjectCB = mCurrFrameResource->ObjectCB.get();
  454.     for(auto& e : mAllRitems)
  455.     {
  456.         // Only update the cbuffer data if the constants have changed.  
  457.         // This needs to be tracked per frame resource.
  458.         if(e->NumFramesDirty > 0)
  459.         {
  460.             XMMATRIX world = XMLoadFloat4x4(&e->World);
  461.             XMMATRIX texTransform = XMLoadFloat4x4(&e->TexTransform);
  462.  
  463.             ObjectConstants objConstants;
  464.             XMStoreFloat4x4(&objConstants.World, XMMatrixTranspose(world));
  465.             XMStoreFloat4x4(&objConstants.TexTransform, XMMatrixTranspose(texTransform));
  466.             objConstants.MaterialIndex = e->Mat->MatCBIndex;
  467.  
  468.             currObjectCB->CopyData(e->ObjCBIndex, objConstants);
  469.  
  470.             // Next FrameResource need to be updated too.
  471.             e->NumFramesDirty--;
  472.         }
  473.     }
  474. }
  475.  
  476. void ShadowMapApp::UpdateMaterialBuffer(const GameTimer& gt)
  477. {
  478.     auto currMaterialBuffer = mCurrFrameResource->MaterialBuffer.get();
  479.     for(auto& e : mMaterials)
  480.     {
  481.         // Only update the cbuffer data if the constants have changed.  If the cbuffer
  482.         // data changes, it needs to be updated for each FrameResource.
  483.         Material* mat = e.second.get();
  484.         if(mat->NumFramesDirty > 0)
  485.         {
  486.             XMMATRIX matTransform = XMLoadFloat4x4(&mat->MatTransform);
  487.  
  488.             MaterialData matData;
  489.             matData.DiffuseAlbedo = mat->DiffuseAlbedo;
  490.             matData.FresnelR0 = mat->FresnelR0;
  491.             matData.Roughness = mat->Roughness;
  492.             XMStoreFloat4x4(&matData.MatTransform, XMMatrixTranspose(matTransform));
  493.             matData.DiffuseMapIndex = mat->DiffuseSrvHeapIndex;
  494.             matData.NormalMapIndex = mat->NormalSrvHeapIndex;
  495.  
  496.             currMaterialBuffer->CopyData(mat->MatCBIndex, matData);
  497.  
  498.             // Next FrameResource need to be updated too.
  499.             mat->NumFramesDirty--;
  500.         }
  501.     }
  502. }
  503.  
  504. void ShadowMapApp::UpdateShadowTransform(const GameTimer& gt)
  505. {
  506.     // Only the first "main" light casts a shadow.
  507.     XMVECTOR lightDir = XMLoadFloat3(&mRotatedLightDirections[0]);
  508.     XMVECTOR lightPos = -2.0f*mSceneBounds.Radius*lightDir;
  509.     XMVECTOR targetPos = XMLoadFloat3(&mSceneBounds.Center);
  510.     XMVECTOR lightUp = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
  511.     XMMATRIX lightView = XMMatrixLookAtLH(lightPos, targetPos, lightUp);
  512.  
  513.     XMStoreFloat3(&mLightPosW, lightPos);
  514.  
  515.     // Transform bounding sphere to light space.
  516.     XMFLOAT3 sphereCenterLS;
  517.     XMStoreFloat3(&sphereCenterLS, XMVector3TransformCoord(targetPos, lightView));
  518.  
  519.     // Ortho frustum in light space encloses scene.
  520.     float l = sphereCenterLS.x - mSceneBounds.Radius;
  521.     float b = sphereCenterLS.y - mSceneBounds.Radius;
  522.     float n = sphereCenterLS.z - mSceneBounds.Radius;
  523.     float r = sphereCenterLS.x + mSceneBounds.Radius;
  524.     float t = sphereCenterLS.y + mSceneBounds.Radius;
  525.     float f = sphereCenterLS.z + mSceneBounds.Radius;
  526.  
  527.     mLightNearZ = n;
  528.     mLightFarZ = f;
  529.     XMMATRIX lightProj = XMMatrixOrthographicOffCenterLH(l, r, b, t, n, f);
  530.  
  531.     // Transform NDC space [-1,+1]^2 to texture space [0,1]^2
  532.     XMMATRIX T(
  533.         0.5f, 0.0f, 0.0f, 0.0f,
  534.         0.0f, -0.5f, 0.0f, 0.0f,
  535.         0.0f, 0.0f, 1.0f, 0.0f,
  536.         0.5f, 0.5f, 0.0f, 1.0f);
  537.  
  538.     XMMATRIX S = lightView*lightProj*T;
  539.     XMStoreFloat4x4(&mLightView, lightView);
  540.     XMStoreFloat4x4(&mLightProj, lightProj);
  541.     XMStoreFloat4x4(&mShadowTransform, S);
  542. }
  543.  
  544. void ShadowMapApp::UpdateMainPassCB(const GameTimer& gt)
  545. {
  546.     XMMATRIX view = mCamera.GetView();
  547.     XMMATRIX proj = mCamera.GetProj();
  548.  
  549.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  550.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  551.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  552.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  553.  
  554.     XMMATRIX shadowTransform = XMLoadFloat4x4(&mShadowTransform);
  555.  
  556.     XMStoreFloat4x4(&mMainPassCB.View, XMMatrixTranspose(view));
  557.     XMStoreFloat4x4(&mMainPassCB.InvView, XMMatrixTranspose(invView));
  558.     XMStoreFloat4x4(&mMainPassCB.Proj, XMMatrixTranspose(proj));
  559.     XMStoreFloat4x4(&mMainPassCB.InvProj, XMMatrixTranspose(invProj));
  560.     XMStoreFloat4x4(&mMainPassCB.ViewProj, XMMatrixTranspose(viewProj));
  561.     XMStoreFloat4x4(&mMainPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  562.     XMStoreFloat4x4(&mMainPassCB.ShadowTransform, XMMatrixTranspose(shadowTransform));
  563.     mMainPassCB.EyePosW = mCamera.GetPosition3f();
  564.     mMainPassCB.RenderTargetSize = XMFLOAT2((float)mClientWidth, (float)mClientHeight);
  565.     mMainPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / mClientWidth, 1.0f / mClientHeight);
  566.     mMainPassCB.NearZ = 1.0f;
  567.     mMainPassCB.FarZ = 1000.0f;
  568.     mMainPassCB.TotalTime = gt.TotalTime();
  569.     mMainPassCB.DeltaTime = gt.DeltaTime();
  570.     mMainPassCB.AmbientLight = { 0.25f, 0.25f, 0.35f, 1.0f };
  571.     mMainPassCB.Lights[0].Direction = mRotatedLightDirections[0];
  572.     mMainPassCB.Lights[0].Strength = { 0.9f, 0.8f, 0.7f };
  573.     mMainPassCB.Lights[1].Direction = mRotatedLightDirections[1];
  574.     mMainPassCB.Lights[1].Strength = { 0.4f, 0.4f, 0.4f };
  575.     mMainPassCB.Lights[2].Direction = mRotatedLightDirections[2];
  576.     mMainPassCB.Lights[2].Strength = { 0.2f, 0.2f, 0.2f };
  577.  
  578.     auto currPassCB = mCurrFrameResource->PassCB.get();
  579.     currPassCB->CopyData(0, mMainPassCB);
  580. }
  581.  
  582. void ShadowMapApp::UpdateShadowPassCB(const GameTimer& gt)
  583. {
  584.     XMMATRIX view = XMLoadFloat4x4(&mLightView);
  585.     XMMATRIX proj = XMLoadFloat4x4(&mLightProj);
  586.  
  587.     XMMATRIX viewProj = XMMatrixMultiply(view, proj);
  588.     XMMATRIX invView = XMMatrixInverse(&XMMatrixDeterminant(view), view);
  589.     XMMATRIX invProj = XMMatrixInverse(&XMMatrixDeterminant(proj), proj);
  590.     XMMATRIX invViewProj = XMMatrixInverse(&XMMatrixDeterminant(viewProj), viewProj);
  591.  
  592.     UINT w = mShadowMap->Width();
  593.     UINT h = mShadowMap->Height();
  594.  
  595.     XMStoreFloat4x4(&mShadowPassCB.View, XMMatrixTranspose(view));
  596.     XMStoreFloat4x4(&mShadowPassCB.InvView, XMMatrixTranspose(invView));
  597.     XMStoreFloat4x4(&mShadowPassCB.Proj, XMMatrixTranspose(proj));
  598.     XMStoreFloat4x4(&mShadowPassCB.InvProj, XMMatrixTranspose(invProj));
  599.     XMStoreFloat4x4(&mShadowPassCB.ViewProj, XMMatrixTranspose(viewProj));
  600.     XMStoreFloat4x4(&mShadowPassCB.InvViewProj, XMMatrixTranspose(invViewProj));
  601.     mShadowPassCB.EyePosW = mLightPosW;
  602.     mShadowPassCB.RenderTargetSize = XMFLOAT2((float)w, (float)h);
  603.     mShadowPassCB.InvRenderTargetSize = XMFLOAT2(1.0f / w, 1.0f / h);
  604.     mShadowPassCB.NearZ = mLightNearZ;
  605.     mShadowPassCB.FarZ = mLightFarZ;
  606.  
  607.     auto currPassCB = mCurrFrameResource->PassCB.get();
  608.     currPassCB->CopyData(1, mShadowPassCB);
  609. }
  610.  
  611. void ShadowMapApp::LoadTextures()
  612. {
  613.     std::vector<std::string> texNames = 
  614.     {
  615.         "bricksDiffuseMap",
  616.         "bricksNormalMap",
  617.         "tileDiffuseMap",
  618.         "tileNormalMap",
  619.         "defaultDiffuseMap",
  620.         "defaultNormalMap",
  621.         "skyCubeMap"
  622.     };
  623.     
  624.     std::vector<std::wstring> texFilenames =
  625.     {
  626.         L"../../Textures/bricks2.dds",
  627.         L"../../Textures/bricks2_nmap.dds",
  628.         L"../../Textures/tile.dds",
  629.         L"../../Textures/tile_nmap.dds",
  630.         L"../../Textures/white1x1.dds",
  631.         L"../../Textures/default_nmap.dds",
  632.         L"../../Textures/desertcube1024.dds"
  633.     };
  634.     
  635.     for(int i = 0; i < (int)texNames.size(); ++i)
  636.     {
  637.         auto texMap = std::make_unique<Texture>();
  638.         texMap->Name = texNames[i];
  639.         texMap->Filename = texFilenames[i];
  640.         ThrowIfFailed(DirectX::CreateDDSTextureFromFile12(md3dDevice.Get(),
  641.             mCommandList.Get(), texMap->Filename.c_str(),
  642.             texMap->Resource, texMap->UploadHeap));
  643.             
  644.         mTextures[texMap->Name] = std::move(texMap);
  645.     }        
  646. }
  647.  
  648. void ShadowMapApp::BuildRootSignature()
  649. {
  650.     CD3DX12_DESCRIPTOR_RANGE texTable0;
  651.     texTable0.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 2, 0, 0);
  652.  
  653.     CD3DX12_DESCRIPTOR_RANGE texTable1;
  654.     texTable1.Init(D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 10, 2, 0);
  655.  
  656.     // Root parameter can be a table, root descriptor or root constants.
  657.     CD3DX12_ROOT_PARAMETER slotRootParameter[5];
  658.  
  659.     // Perfomance TIP: Order from most frequent to least frequent.
  660.     slotRootParameter[0].InitAsConstantBufferView(0);
  661.     slotRootParameter[1].InitAsConstantBufferView(1);
  662.     slotRootParameter[2].InitAsShaderResourceView(0, 1);
  663.     slotRootParameter[3].InitAsDescriptorTable(1, &texTable0, D3D12_SHADER_VISIBILITY_PIXEL);
  664.     slotRootParameter[4].InitAsDescriptorTable(1, &texTable1, D3D12_SHADER_VISIBILITY_PIXEL);
  665.  
  666.  
  667.     auto staticSamplers = GetStaticSamplers();
  668.  
  669.     // A root signature is an array of root parameters.
  670.     CD3DX12_ROOT_SIGNATURE_DESC rootSigDesc(5, slotRootParameter,
  671.         (UINT)staticSamplers.size(), staticSamplers.data(),
  672.         D3D12_ROOT_SIGNATURE_FLAG_ALLOW_INPUT_ASSEMBLER_INPUT_LAYOUT);
  673.  
  674.     // create a root signature with a single slot which points to a descriptor range consisting of a single constant buffer
  675.     ComPtr<ID3DBlob> serializedRootSig = nullptr;
  676.     ComPtr<ID3DBlob> errorBlob = nullptr;
  677.     HRESULT hr = D3D12SerializeRootSignature(&rootSigDesc, D3D_ROOT_SIGNATURE_VERSION_1,
  678.         serializedRootSig.GetAddressOf(), errorBlob.GetAddressOf());
  679.  
  680.     if(errorBlob != nullptr)
  681.     {
  682.         ::OutputDebugStringA((char*)errorBlob->GetBufferPointer());
  683.     }
  684.     ThrowIfFailed(hr);
  685.  
  686.     ThrowIfFailed(md3dDevice->CreateRootSignature(
  687.         0,
  688.         serializedRootSig->GetBufferPointer(),
  689.         serializedRootSig->GetBufferSize(),
  690.         IID_PPV_ARGS(mRootSignature.GetAddressOf())));
  691. }
  692.  
  693. void ShadowMapApp::BuildDescriptorHeaps()
  694. {
  695.     //
  696.     // Create the SRV heap.
  697.     //
  698.     D3D12_DESCRIPTOR_HEAP_DESC srvHeapDesc = {};
  699.     srvHeapDesc.NumDescriptors = 14;
  700.     srvHeapDesc.Type = D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV;
  701.     srvHeapDesc.Flags = D3D12_DESCRIPTOR_HEAP_FLAG_SHADER_VISIBLE;
  702.     ThrowIfFailed(md3dDevice->CreateDescriptorHeap(&srvHeapDesc, IID_PPV_ARGS(&mSrvDescriptorHeap)));
  703.  
  704.     //
  705.     // Fill out the heap with actual descriptors.
  706.     //
  707.     CD3DX12_CPU_DESCRIPTOR_HANDLE hDescriptor(mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart());
  708.  
  709.     std::vector<ComPtr<ID3D12Resource>> tex2DList = 
  710.     {
  711.         mTextures["bricksDiffuseMap"]->Resource,
  712.         mTextures["bricksNormalMap"]->Resource,
  713.         mTextures["tileDiffuseMap"]->Resource,
  714.         mTextures["tileNormalMap"]->Resource,
  715.         mTextures["defaultDiffuseMap"]->Resource,
  716.         mTextures["defaultNormalMap"]->Resource
  717.     };
  718.     
  719.     auto skyCubeMap = mTextures["skyCubeMap"]->Resource;
  720.  
  721.     D3D12_SHADER_RESOURCE_VIEW_DESC srvDesc = {};
  722.     srvDesc.Shader4ComponentMapping = D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING;
  723.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  724.     srvDesc.Texture2D.MostDetailedMip = 0;
  725.     srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  726.     
  727.     for(UINT i = 0; i < (UINT)tex2DList.size(); ++i)
  728.     {
  729.         srvDesc.Format = tex2DList[i]->GetDesc().Format;
  730.         srvDesc.Texture2D.MipLevels = tex2DList[i]->GetDesc().MipLevels;
  731.         md3dDevice->CreateShaderResourceView(tex2DList[i].Get(), &srvDesc, hDescriptor);
  732.  
  733.         // next descriptor
  734.         hDescriptor.Offset(1, mCbvSrvUavDescriptorSize);
  735.     }
  736.     
  737.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURECUBE;
  738.     srvDesc.TextureCube.MostDetailedMip = 0;
  739.     srvDesc.TextureCube.MipLevels = skyCubeMap->GetDesc().MipLevels;
  740.     srvDesc.TextureCube.ResourceMinLODClamp = 0.0f;
  741.     srvDesc.Format = skyCubeMap->GetDesc().Format;
  742.     md3dDevice->CreateShaderResourceView(skyCubeMap.Get(), &srvDesc, hDescriptor);
  743.     
  744.     mSkyTexHeapIndex = (UINT)tex2DList.size();
  745.     mShadowMapHeapIndex = mSkyTexHeapIndex + 1;
  746.  
  747.     mNullCubeSrvIndex = mShadowMapHeapIndex + 1;
  748.     mNullTexSrvIndex = mNullCubeSrvIndex + 1;
  749.  
  750.     auto srvCpuStart = mSrvDescriptorHeap->GetCPUDescriptorHandleForHeapStart();
  751.     auto srvGpuStart = mSrvDescriptorHeap->GetGPUDescriptorHandleForHeapStart();
  752.     auto dsvCpuStart = mDsvHeap->GetCPUDescriptorHandleForHeapStart();
  753.  
  754.  
  755.     auto nullSrv = CD3DX12_CPU_DESCRIPTOR_HANDLE(srvCpuStart, mNullCubeSrvIndex, mCbvSrvUavDescriptorSize);
  756.     mNullSrv = CD3DX12_GPU_DESCRIPTOR_HANDLE(srvGpuStart, mNullCubeSrvIndex, mCbvSrvUavDescriptorSize);
  757.  
  758.     md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
  759.     nullSrv.Offset(1, mCbvSrvUavDescriptorSize);
  760.  
  761.     srvDesc.ViewDimension = D3D12_SRV_DIMENSION_TEXTURE2D;
  762.     srvDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
  763.     srvDesc.Texture2D.MostDetailedMip = 0;
  764.     srvDesc.Texture2D.MipLevels = 1;
  765.     srvDesc.Texture2D.ResourceMinLODClamp = 0.0f;
  766.     md3dDevice->CreateShaderResourceView(nullptr, &srvDesc, nullSrv);
  767.     
  768.     mShadowMap->BuildDescriptors(
  769.         CD3DX12_CPU_DESCRIPTOR_HANDLE(srvCpuStart, mShadowMapHeapIndex, mCbvSrvUavDescriptorSize),
  770.         CD3DX12_GPU_DESCRIPTOR_HANDLE(srvGpuStart, mShadowMapHeapIndex, mCbvSrvUavDescriptorSize),
  771.         CD3DX12_CPU_DESCRIPTOR_HANDLE(dsvCpuStart, 1, mDsvDescriptorSize));
  772. }
  773.  
  774. void ShadowMapApp::BuildShadersAndInputLayout()
  775. {
  776.     const D3D_SHADER_MACRO alphaTestDefines[] =
  777.     {
  778.         "ALPHA_TEST", "1",
  779.         NULL, NULL
  780.     };
  781.  
  782.     mShaders["standardVS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "VS", "vs_5_1");
  783.     mShaders["opaquePS"] = d3dUtil::CompileShader(L"Shaders\\Default.hlsl", nullptr, "PS", "ps_5_1");
  784.  
  785.     mShaders["shadowVS"] = d3dUtil::CompileShader(L"Shaders\\Shadows.hlsl", nullptr, "VS", "vs_5_1");
  786.     mShaders["shadowOpaquePS"] = d3dUtil::CompileShader(L"Shaders\\Shadows.hlsl", nullptr, "PS", "ps_5_1");
  787.     mShaders["shadowAlphaTestedPS"] = d3dUtil::CompileShader(L"Shaders\\Shadows.hlsl", alphaTestDefines, "PS", "ps_5_1");
  788.     
  789.     mShaders["debugVS"] = d3dUtil::CompileShader(L"Shaders\\ShadowDebug.hlsl", nullptr, "VS", "vs_5_1");
  790.     mShaders["debugPS"] = d3dUtil::CompileShader(L"Shaders\\ShadowDebug.hlsl", nullptr, "PS", "ps_5_1");
  791.  
  792.     mShaders["skyVS"] = d3dUtil::CompileShader(L"Shaders\\Sky.hlsl", nullptr, "VS", "vs_5_1");
  793.     mShaders["skyPS"] = d3dUtil::CompileShader(L"Shaders\\Sky.hlsl", nullptr, "PS", "ps_5_1");
  794.  
  795.     mInputLayout =
  796.     {
  797.         { "POSITION", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 0, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  798.         { "NORMAL", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 12, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  799.         { "TEXCOORD", 0, DXGI_FORMAT_R32G32_FLOAT, 0, 24, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  800.         { "TANGENT", 0, DXGI_FORMAT_R32G32B32_FLOAT, 0, 32, D3D12_INPUT_CLASSIFICATION_PER_VERTEX_DATA, 0 },
  801.     };
  802. }
  803.  
  804. void ShadowMapApp::BuildShapeGeometry()
  805. {
  806.     GeometryGenerator geoGen;
  807.     GeometryGenerator::MeshData box = geoGen.CreateBox(1.0f, 1.0f, 1.0f, 3);
  808.     GeometryGenerator::MeshData grid = geoGen.CreateGrid(20.0f, 30.0f, 60, 40);
  809.     GeometryGenerator::MeshData sphere = geoGen.CreateSphere(0.5f, 20, 20);
  810.     GeometryGenerator::MeshData cylinder = geoGen.CreateCylinder(0.5f, 0.3f, 3.0f, 20, 20);
  811.     GeometryGenerator::MeshData quad = geoGen.CreateQuad(0.0f, 0.0f, 1.0f, 1.0f, 0.0f);
  812.     
  813.     //
  814.     // We are concatenating all the geometry into one big vertex/index buffer.  So
  815.     // define the regions in the buffer each submesh covers.
  816.     //
  817.  
  818.     // Cache the vertex offsets to each object in the concatenated vertex buffer.
  819.     UINT boxVertexOffset = 0;
  820.     UINT gridVertexOffset = (UINT)box.Vertices.size();
  821.     UINT sphereVertexOffset = gridVertexOffset + (UINT)grid.Vertices.size();
  822.     UINT cylinderVertexOffset = sphereVertexOffset + (UINT)sphere.Vertices.size();
  823.     UINT quadVertexOffset = cylinderVertexOffset + (UINT)cylinder.Vertices.size();
  824.  
  825.     // Cache the starting index for each object in the concatenated index buffer.
  826.     UINT boxIndexOffset = 0;
  827.     UINT gridIndexOffset = (UINT)box.Indices32.size();
  828.     UINT sphereIndexOffset = gridIndexOffset + (UINT)grid.Indices32.size();
  829.     UINT cylinderIndexOffset = sphereIndexOffset + (UINT)sphere.Indices32.size();
  830.     UINT quadIndexOffset = cylinderIndexOffset + (UINT)cylinder.Indices32.size();
  831.  
  832.     SubmeshGeometry boxSubmesh;
  833.     boxSubmesh.IndexCount = (UINT)box.Indices32.size();
  834.     boxSubmesh.StartIndexLocation = boxIndexOffset;
  835.     boxSubmesh.BaseVertexLocation = boxVertexOffset;
  836.  
  837.     SubmeshGeometry gridSubmesh;
  838.     gridSubmesh.IndexCount = (UINT)grid.Indices32.size();
  839.     gridSubmesh.StartIndexLocation = gridIndexOffset;
  840.     gridSubmesh.BaseVertexLocation = gridVertexOffset;
  841.  
  842.     SubmeshGeometry sphereSubmesh;
  843.     sphereSubmesh.IndexCount = (UINT)sphere.Indices32.size();
  844.     sphereSubmesh.StartIndexLocation = sphereIndexOffset;
  845.     sphereSubmesh.BaseVertexLocation = sphereVertexOffset;
  846.  
  847.     SubmeshGeometry cylinderSubmesh;
  848.     cylinderSubmesh.IndexCount = (UINT)cylinder.Indices32.size();
  849.     cylinderSubmesh.StartIndexLocation = cylinderIndexOffset;
  850.     cylinderSubmesh.BaseVertexLocation = cylinderVertexOffset;
  851.  
  852.     SubmeshGeometry quadSubmesh;
  853.     quadSubmesh.IndexCount = (UINT)quad.Indices32.size();
  854.     quadSubmesh.StartIndexLocation = quadIndexOffset;
  855.     quadSubmesh.BaseVertexLocation = quadVertexOffset;
  856.  
  857.     //
  858.     // Extract the vertex elements we are interested in and pack the
  859.     // vertices of all the meshes into one vertex buffer.
  860.     //
  861.  
  862.     auto totalVertexCount =
  863.         box.Vertices.size() +
  864.         grid.Vertices.size() +
  865.         sphere.Vertices.size() +
  866.         cylinder.Vertices.size() + 
  867.         quad.Vertices.size();
  868.  
  869.     std::vector<Vertex> vertices(totalVertexCount);
  870.  
  871.     UINT k = 0;
  872.     for(size_t i = 0; i < box.Vertices.size(); ++i, ++k)
  873.     {
  874.         vertices[k].Pos = box.Vertices[i].Position;
  875.         vertices[k].Normal = box.Vertices[i].Normal;
  876.         vertices[k].TexC = box.Vertices[i].TexC;
  877.         vertices[k].TangentU = box.Vertices[i].TangentU;
  878.     }
  879.  
  880.     for(size_t i = 0; i < grid.Vertices.size(); ++i, ++k)
  881.     {
  882.         vertices[k].Pos = grid.Vertices[i].Position;
  883.         vertices[k].Normal = grid.Vertices[i].Normal;
  884.         vertices[k].TexC = grid.Vertices[i].TexC;
  885.         vertices[k].TangentU = grid.Vertices[i].TangentU;
  886.     }
  887.  
  888.     for(size_t i = 0; i < sphere.Vertices.size(); ++i, ++k)
  889.     {
  890.         vertices[k].Pos = sphere.Vertices[i].Position;
  891.         vertices[k].Normal = sphere.Vertices[i].Normal;
  892.         vertices[k].TexC = sphere.Vertices[i].TexC;
  893.         vertices[k].TangentU = sphere.Vertices[i].TangentU;
  894.     }
  895.  
  896.     for(size_t i = 0; i < cylinder.Vertices.size(); ++i, ++k)
  897.     {
  898.         vertices[k].Pos = cylinder.Vertices[i].Position;
  899.         vertices[k].Normal = cylinder.Vertices[i].Normal;
  900.         vertices[k].TexC = cylinder.Vertices[i].TexC;
  901.         vertices[k].TangentU = cylinder.Vertices[i].TangentU;
  902.     }
  903.  
  904.     for(int i = 0; i < quad.Vertices.size(); ++i, ++k)
  905.     {
  906.         vertices[k].Pos = quad.Vertices[i].Position;
  907.         vertices[k].Normal = quad.Vertices[i].Normal;
  908.         vertices[k].TexC = quad.Vertices[i].TexC;
  909.         vertices[k].TangentU = quad.Vertices[i].TangentU;
  910.     }
  911.  
  912.     std::vector<std::uint16_t> indices;
  913.     indices.insert(indices.end(), std::begin(box.GetIndices16()), std::end(box.GetIndices16()));
  914.     indices.insert(indices.end(), std::begin(grid.GetIndices16()), std::end(grid.GetIndices16()));
  915.     indices.insert(indices.end(), std::begin(sphere.GetIndices16()), std::end(sphere.GetIndices16()));
  916.     indices.insert(indices.end(), std::begin(cylinder.GetIndices16()), std::end(cylinder.GetIndices16()));
  917.     indices.insert(indices.end(), std::begin(quad.GetIndices16()), std::end(quad.GetIndices16()));
  918.  
  919.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  920.     const UINT ibByteSize = (UINT)indices.size()  * sizeof(std::uint16_t);
  921.  
  922.     auto geo = std::make_unique<MeshGeometry>();
  923.     geo->Name = "shapeGeo";
  924.  
  925.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  926.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  927.  
  928.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  929.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  930.  
  931.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  932.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  933.  
  934.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  935.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  936.  
  937.     geo->VertexByteStride = sizeof(Vertex);
  938.     geo->VertexBufferByteSize = vbByteSize;
  939.     geo->IndexFormat = DXGI_FORMAT_R16_UINT;
  940.     geo->IndexBufferByteSize = ibByteSize;
  941.  
  942.     geo->DrawArgs["box"] = boxSubmesh;
  943.     geo->DrawArgs["grid"] = gridSubmesh;
  944.     geo->DrawArgs["sphere"] = sphereSubmesh;
  945.     geo->DrawArgs["cylinder"] = cylinderSubmesh;
  946.     geo->DrawArgs["quad"] = quadSubmesh;
  947.  
  948.     mGeometries[geo->Name] = std::move(geo);
  949. }
  950.  
  951. void ShadowMapApp::BuildSkullGeometry()
  952. {
  953.     std::ifstream fin("Models/skull.txt");
  954.  
  955.     if (!fin)
  956.     {
  957.         MessageBox(0, L"Models/skull.txt not found.", 0, 0);
  958.         return;
  959.     }
  960.  
  961.     UINT vcount = 0;
  962.     UINT tcount = 0;
  963.     std::string ignore;
  964.  
  965.     fin >> ignore >> vcount;
  966.     fin >> ignore >> tcount;
  967.     fin >> ignore >> ignore >> ignore >> ignore;
  968.  
  969.     XMFLOAT3 vMinf3(+MathHelper::Infinity, +MathHelper::Infinity, +MathHelper::Infinity);
  970.     XMFLOAT3 vMaxf3(-MathHelper::Infinity, -MathHelper::Infinity, -MathHelper::Infinity);
  971.  
  972.     XMVECTOR vMin = XMLoadFloat3(&vMinf3);
  973.     XMVECTOR vMax = XMLoadFloat3(&vMaxf3);
  974.  
  975.     std::vector<Vertex> vertices(vcount);
  976.     for (UINT i = 0; i < vcount; ++i)
  977.     {
  978.         fin >> vertices[i].Pos.x >> vertices[i].Pos.y >> vertices[i].Pos.z;
  979.         fin >> vertices[i].Normal.x >> vertices[i].Normal.y >> vertices[i].Normal.z;
  980.  
  981.         vertices[i].TexC = { 0.0f, 0.0f };
  982.  
  983.         XMVECTOR P = XMLoadFloat3(&vertices[i].Pos);
  984.  
  985.         XMVECTOR N = XMLoadFloat3(&vertices[i].Normal);
  986.  
  987.         // Generate a tangent vector so normal mapping works.  We aren't applying
  988.         // a texture map to the skull, so we just need any tangent vector so that
  989.         // the math works out to give us the original interpolated vertex normal.
  990.         XMVECTOR up = XMVectorSet(0.0f, 1.0f, 0.0f, 0.0f);
  991.         if(fabsf(XMVectorGetX(XMVector3Dot(N, up))) < 1.0f - 0.001f)
  992.         {
  993.             XMVECTOR T = XMVector3Normalize(XMVector3Cross(up, N));
  994.             XMStoreFloat3(&vertices[i].TangentU, T);
  995.         }
  996.         else
  997.         {
  998.             up = XMVectorSet(0.0f, 0.0f, 1.0f, 0.0f);
  999.             XMVECTOR T = XMVector3Normalize(XMVector3Cross(N, up));
  1000.             XMStoreFloat3(&vertices[i].TangentU, T);
  1001.         }
  1002.         
  1003.  
  1004.         vMin = XMVectorMin(vMin, P);
  1005.         vMax = XMVectorMax(vMax, P);
  1006.     }
  1007.  
  1008.     BoundingBox bounds;
  1009.     XMStoreFloat3(&bounds.Center, 0.5f*(vMin + vMax));
  1010.     XMStoreFloat3(&bounds.Extents, 0.5f*(vMax - vMin));
  1011.  
  1012.     fin >> ignore;
  1013.     fin >> ignore;
  1014.     fin >> ignore;
  1015.  
  1016.     std::vector<std::int32_t> indices(3 * tcount);
  1017.     for (UINT i = 0; i < tcount; ++i)
  1018.     {
  1019.         fin >> indices[i * 3 + 0] >> indices[i * 3 + 1] >> indices[i * 3 + 2];
  1020.     }
  1021.  
  1022.     fin.close();
  1023.  
  1024.     //
  1025.     // Pack the indices of all the meshes into one index buffer.
  1026.     //
  1027.  
  1028.     const UINT vbByteSize = (UINT)vertices.size() * sizeof(Vertex);
  1029.  
  1030.     const UINT ibByteSize = (UINT)indices.size() * sizeof(std::int32_t);
  1031.  
  1032.     auto geo = std::make_unique<MeshGeometry>();
  1033.     geo->Name = "skullGeo";
  1034.  
  1035.     ThrowIfFailed(D3DCreateBlob(vbByteSize, &geo->VertexBufferCPU));
  1036.     CopyMemory(geo->VertexBufferCPU->GetBufferPointer(), vertices.data(), vbByteSize);
  1037.  
  1038.     ThrowIfFailed(D3DCreateBlob(ibByteSize, &geo->IndexBufferCPU));
  1039.     CopyMemory(geo->IndexBufferCPU->GetBufferPointer(), indices.data(), ibByteSize);
  1040.  
  1041.     geo->VertexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  1042.         mCommandList.Get(), vertices.data(), vbByteSize, geo->VertexBufferUploader);
  1043.  
  1044.     geo->IndexBufferGPU = d3dUtil::CreateDefaultBuffer(md3dDevice.Get(),
  1045.         mCommandList.Get(), indices.data(), ibByteSize, geo->IndexBufferUploader);
  1046.  
  1047.     geo->VertexByteStride = sizeof(Vertex);
  1048.     geo->VertexBufferByteSize = vbByteSize;
  1049.     geo->IndexFormat = DXGI_FORMAT_R32_UINT;
  1050.     geo->IndexBufferByteSize = ibByteSize;
  1051.  
  1052.     SubmeshGeometry submesh;
  1053.     submesh.IndexCount = (UINT)indices.size();
  1054.     submesh.StartIndexLocation = 0;
  1055.     submesh.BaseVertexLocation = 0;
  1056.     submesh.Bounds = bounds;
  1057.  
  1058.     geo->DrawArgs["skull"] = submesh;
  1059.  
  1060.     mGeometries[geo->Name] = std::move(geo);
  1061. }
  1062.  
  1063. void ShadowMapApp::BuildPSOs()
  1064. {
  1065.     D3D12_GRAPHICS_PIPELINE_STATE_DESC opaquePsoDesc;
  1066.  
  1067.     //
  1068.     // PSO for opaque objects.
  1069.     //
  1070.     ZeroMemory(&opaquePsoDesc, sizeof(D3D12_GRAPHICS_PIPELINE_STATE_DESC));
  1071.     opaquePsoDesc.InputLayout = { mInputLayout.data(), (UINT)mInputLayout.size() };
  1072.     opaquePsoDesc.pRootSignature = mRootSignature.Get();
  1073.     opaquePsoDesc.VS = 
  1074.     { 
  1075.         reinterpret_cast<BYTE*>(mShaders["standardVS"]->GetBufferPointer()), 
  1076.         mShaders["standardVS"]->GetBufferSize()
  1077.     };
  1078.     opaquePsoDesc.PS = 
  1079.     { 
  1080.         reinterpret_cast<BYTE*>(mShaders["opaquePS"]->GetBufferPointer()),
  1081.         mShaders["opaquePS"]->GetBufferSize()
  1082.     };
  1083.     opaquePsoDesc.RasterizerState = CD3DX12_RASTERIZER_DESC(D3D12_DEFAULT);
  1084.     opaquePsoDesc.BlendState = CD3DX12_BLEND_DESC(D3D12_DEFAULT);
  1085.     opaquePsoDesc.DepthStencilState = CD3DX12_DEPTH_STENCIL_DESC(D3D12_DEFAULT);
  1086.     opaquePsoDesc.SampleMask = UINT_MAX;
  1087.     opaquePsoDesc.PrimitiveTopologyType = D3D12_PRIMITIVE_TOPOLOGY_TYPE_TRIANGLE;
  1088.     opaquePsoDesc.NumRenderTargets = 1;
  1089.     opaquePsoDesc.RTVFormats[0] = mBackBufferFormat;
  1090.     opaquePsoDesc.SampleDesc.Count = m4xMsaaState ? 4 : 1;
  1091.     opaquePsoDesc.SampleDesc.Quality = m4xMsaaState ? (m4xMsaaQuality - 1) : 0;
  1092.     opaquePsoDesc.DSVFormat = mDepthStencilFormat;
  1093.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&opaquePsoDesc, IID_PPV_ARGS(&mPSOs["opaque"])));
  1094.  
  1095.     //
  1096.     // PSO for shadow map pass.
  1097.     //
  1098.     D3D12_GRAPHICS_PIPELINE_STATE_DESC smapPsoDesc = opaquePsoDesc;
  1099.     smapPsoDesc.RasterizerState.DepthBias = 100000;
  1100.     smapPsoDesc.RasterizerState.DepthBiasClamp = 0.0f;
  1101.     smapPsoDesc.RasterizerState.SlopeScaledDepthBias = 1.0f;
  1102.     smapPsoDesc.pRootSignature = mRootSignature.Get();
  1103.     smapPsoDesc.VS =
  1104.     {
  1105.         reinterpret_cast<BYTE*>(mShaders["shadowVS"]->GetBufferPointer()),
  1106.         mShaders["shadowVS"]->GetBufferSize()
  1107.     };
  1108.     smapPsoDesc.PS =
  1109.     {
  1110.         reinterpret_cast<BYTE*>(mShaders["shadowOpaquePS"]->GetBufferPointer()),
  1111.         mShaders["shadowOpaquePS"]->GetBufferSize()
  1112.     };
  1113.     
  1114.     // Shadow map pass does not have a render target.
  1115.     smapPsoDesc.RTVFormats[0] = DXGI_FORMAT_UNKNOWN;
  1116.     smapPsoDesc.NumRenderTargets = 0;
  1117.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&smapPsoDesc, IID_PPV_ARGS(&mPSOs["shadow_opaque"])));
  1118.  
  1119.     //
  1120.     // PSO for debug layer.
  1121.     //
  1122.     D3D12_GRAPHICS_PIPELINE_STATE_DESC debugPsoDesc = opaquePsoDesc;
  1123.     debugPsoDesc.pRootSignature = mRootSignature.Get();
  1124.     debugPsoDesc.VS =
  1125.     {
  1126.         reinterpret_cast<BYTE*>(mShaders["debugVS"]->GetBufferPointer()),
  1127.         mShaders["debugVS"]->GetBufferSize()
  1128.     };
  1129.     debugPsoDesc.PS =
  1130.     {
  1131.         reinterpret_cast<BYTE*>(mShaders["debugPS"]->GetBufferPointer()),
  1132.         mShaders["debugPS"]->GetBufferSize()
  1133.     };
  1134.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&debugPsoDesc, IID_PPV_ARGS(&mPSOs["debug"])));
  1135.  
  1136.     //
  1137.     // PSO for sky.
  1138.     //
  1139.     D3D12_GRAPHICS_PIPELINE_STATE_DESC skyPsoDesc = opaquePsoDesc;
  1140.  
  1141.     // The camera is inside the sky sphere, so just turn off culling.
  1142.     skyPsoDesc.RasterizerState.CullMode = D3D12_CULL_MODE_NONE;
  1143.  
  1144.     // Make sure the depth function is LESS_EQUAL and not just LESS.  
  1145.     // Otherwise, the normalized depth values at z = 1 (NDC) will 
  1146.     // fail the depth test if the depth buffer was cleared to 1.
  1147.     skyPsoDesc.DepthStencilState.DepthFunc = D3D12_COMPARISON_FUNC_LESS_EQUAL;
  1148.     skyPsoDesc.pRootSignature = mRootSignature.Get();
  1149.     skyPsoDesc.VS =
  1150.     {
  1151.         reinterpret_cast<BYTE*>(mShaders["skyVS"]->GetBufferPointer()),
  1152.         mShaders["skyVS"]->GetBufferSize()
  1153.     };
  1154.     skyPsoDesc.PS =
  1155.     {
  1156.         reinterpret_cast<BYTE*>(mShaders["skyPS"]->GetBufferPointer()),
  1157.         mShaders["skyPS"]->GetBufferSize()
  1158.     };
  1159.     ThrowIfFailed(md3dDevice->CreateGraphicsPipelineState(&skyPsoDesc, IID_PPV_ARGS(&mPSOs["sky"])));
  1160.  
  1161. }
  1162.  
  1163. void ShadowMapApp::BuildFrameResources()
  1164. {
  1165.     for(int i = 0; i < gNumFrameResources; ++i)
  1166.     {
  1167.         mFrameResources.push_back(std::make_unique<FrameResource>(md3dDevice.Get(),
  1168.             2, (UINT)mAllRitems.size(), (UINT)mMaterials.size()));
  1169.     }
  1170. }
  1171.  
  1172. void ShadowMapApp::BuildMaterials()
  1173. {
  1174.     auto bricks0 = std::make_unique<Material>();
  1175.     bricks0->Name = "bricks0";
  1176.     bricks0->MatCBIndex = 0;
  1177.     bricks0->DiffuseSrvHeapIndex = 0;
  1178.     bricks0->NormalSrvHeapIndex = 1;
  1179.     bricks0->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  1180.     bricks0->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  1181.     bricks0->Roughness = 0.3f;
  1182.  
  1183.     auto tile0 = std::make_unique<Material>();
  1184.     tile0->Name = "tile0";
  1185.     tile0->MatCBIndex = 1;
  1186.     tile0->DiffuseSrvHeapIndex = 2;
  1187.     tile0->NormalSrvHeapIndex = 3;
  1188.     tile0->DiffuseAlbedo = XMFLOAT4(0.9f, 0.9f, 0.9f, 1.0f);
  1189.     tile0->FresnelR0 = XMFLOAT3(0.2f, 0.2f, 0.2f);
  1190.     tile0->Roughness = 0.1f;
  1191.  
  1192.     auto mirror0 = std::make_unique<Material>();
  1193.     mirror0->Name = "mirror0";
  1194.     mirror0->MatCBIndex = 2;
  1195.     mirror0->DiffuseSrvHeapIndex = 4;
  1196.     mirror0->NormalSrvHeapIndex = 5;
  1197.     mirror0->DiffuseAlbedo = XMFLOAT4(0.0f, 0.0f, 0.0f, 1.0f);
  1198.     mirror0->FresnelR0 = XMFLOAT3(0.98f, 0.97f, 0.95f);
  1199.     mirror0->Roughness = 0.1f;
  1200.  
  1201.     auto skullMat = std::make_unique<Material>();
  1202.     skullMat->Name = "skullMat";
  1203.     skullMat->MatCBIndex = 3;
  1204.     skullMat->DiffuseSrvHeapIndex = 4;
  1205.     skullMat->NormalSrvHeapIndex = 5;
  1206.     skullMat->DiffuseAlbedo = XMFLOAT4(0.3f, 0.3f, 0.3f, 1.0f);
  1207.     skullMat->FresnelR0 = XMFLOAT3(0.6f, 0.6f, 0.6f);
  1208.     skullMat->Roughness = 0.2f;
  1209.  
  1210.     auto sky = std::make_unique<Material>();
  1211.     sky->Name = "sky";
  1212.     sky->MatCBIndex = 4;
  1213.     sky->DiffuseSrvHeapIndex = 6;
  1214.     sky->NormalSrvHeapIndex = 7;
  1215.     sky->DiffuseAlbedo = XMFLOAT4(1.0f, 1.0f, 1.0f, 1.0f);
  1216.     sky->FresnelR0 = XMFLOAT3(0.1f, 0.1f, 0.1f);
  1217.     sky->Roughness = 1.0f;
  1218.  
  1219.     mMaterials["bricks0"] = std::move(bricks0);
  1220.     mMaterials["tile0"] = std::move(tile0);
  1221.     mMaterials["mirror0"] = std::move(mirror0);
  1222.     mMaterials["skullMat"] = std::move(skullMat);
  1223.     mMaterials["sky"] = std::move(sky);
  1224. }
  1225.  
  1226. void ShadowMapApp::BuildRenderItems()
  1227. {
  1228.     auto skyRitem = std::make_unique<RenderItem>();
  1229.     XMStoreFloat4x4(&skyRitem->World, XMMatrixScaling(5000.0f, 5000.0f, 5000.0f));
  1230.     skyRitem->TexTransform = MathHelper::Identity4x4();
  1231.     skyRitem->ObjCBIndex = 0;
  1232.     skyRitem->Mat = mMaterials["sky"].get();
  1233.     skyRitem->Geo = mGeometries["shapeGeo"].get();
  1234.     skyRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1235.     skyRitem->IndexCount = skyRitem->Geo->DrawArgs["sphere"].IndexCount;
  1236.     skyRitem->StartIndexLocation = skyRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1237.     skyRitem->BaseVertexLocation = skyRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1238.  
  1239.     mRitemLayer[(int)RenderLayer::Sky].push_back(skyRitem.get());
  1240.     mAllRitems.push_back(std::move(skyRitem));
  1241.     
  1242.     auto quadRitem = std::make_unique<RenderItem>();
  1243.     quadRitem->World = MathHelper::Identity4x4();
  1244.     quadRitem->TexTransform = MathHelper::Identity4x4();
  1245.     quadRitem->ObjCBIndex = 1;
  1246.     quadRitem->Mat = mMaterials["bricks0"].get();
  1247.     quadRitem->Geo = mGeometries["shapeGeo"].get();
  1248.     quadRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1249.     quadRitem->IndexCount = quadRitem->Geo->DrawArgs["quad"].IndexCount;
  1250.     quadRitem->StartIndexLocation = quadRitem->Geo->DrawArgs["quad"].StartIndexLocation;
  1251.     quadRitem->BaseVertexLocation = quadRitem->Geo->DrawArgs["quad"].BaseVertexLocation;
  1252.  
  1253.     mRitemLayer[(int)RenderLayer::Debug].push_back(quadRitem.get());
  1254.     mAllRitems.push_back(std::move(quadRitem));
  1255.     
  1256.     auto boxRitem = std::make_unique<RenderItem>();
  1257.     XMStoreFloat4x4(&boxRitem->World, XMMatrixScaling(2.0f, 1.0f, 2.0f)*XMMatrixTranslation(0.0f, 0.5f, 0.0f));
  1258.     XMStoreFloat4x4(&boxRitem->TexTransform, XMMatrixScaling(1.0f, 0.5f, 1.0f));
  1259.     boxRitem->ObjCBIndex = 2;
  1260.     boxRitem->Mat = mMaterials["bricks0"].get();
  1261.     boxRitem->Geo = mGeometries["shapeGeo"].get();
  1262.     boxRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1263.     boxRitem->IndexCount = boxRitem->Geo->DrawArgs["box"].IndexCount;
  1264.     boxRitem->StartIndexLocation = boxRitem->Geo->DrawArgs["box"].StartIndexLocation;
  1265.     boxRitem->BaseVertexLocation = boxRitem->Geo->DrawArgs["box"].BaseVertexLocation;
  1266.  
  1267.     mRitemLayer[(int)RenderLayer::Opaque].push_back(boxRitem.get());
  1268.     mAllRitems.push_back(std::move(boxRitem));
  1269.  
  1270.     auto skullRitem = std::make_unique<RenderItem>();
  1271.     XMStoreFloat4x4(&skullRitem->World, XMMatrixScaling(0.4f, 0.4f, 0.4f)*XMMatrixTranslation(0.0f, 1.0f, 0.0f));
  1272.     skullRitem->TexTransform = MathHelper::Identity4x4();
  1273.     skullRitem->ObjCBIndex = 3;
  1274.     skullRitem->Mat = mMaterials["skullMat"].get();
  1275.     skullRitem->Geo = mGeometries["skullGeo"].get();
  1276.     skullRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1277.     skullRitem->IndexCount = skullRitem->Geo->DrawArgs["skull"].IndexCount;
  1278.     skullRitem->StartIndexLocation = skullRitem->Geo->DrawArgs["skull"].StartIndexLocation;
  1279.     skullRitem->BaseVertexLocation = skullRitem->Geo->DrawArgs["skull"].BaseVertexLocation;
  1280.  
  1281.     mRitemLayer[(int)RenderLayer::Opaque].push_back(skullRitem.get());
  1282.     mAllRitems.push_back(std::move(skullRitem));
  1283.  
  1284.     auto gridRitem = std::make_unique<RenderItem>();
  1285.     gridRitem->World = MathHelper::Identity4x4();
  1286.     XMStoreFloat4x4(&gridRitem->TexTransform, XMMatrixScaling(8.0f, 8.0f, 1.0f));
  1287.     gridRitem->ObjCBIndex = 4;
  1288.     gridRitem->Mat = mMaterials["tile0"].get();
  1289.     gridRitem->Geo = mGeometries["shapeGeo"].get();
  1290.     gridRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1291.     gridRitem->IndexCount = gridRitem->Geo->DrawArgs["grid"].IndexCount;
  1292.     gridRitem->StartIndexLocation = gridRitem->Geo->DrawArgs["grid"].StartIndexLocation;
  1293.     gridRitem->BaseVertexLocation = gridRitem->Geo->DrawArgs["grid"].BaseVertexLocation;
  1294.  
  1295.     mRitemLayer[(int)RenderLayer::Opaque].push_back(gridRitem.get());
  1296.     mAllRitems.push_back(std::move(gridRitem));
  1297.  
  1298.     XMMATRIX brickTexTransform = XMMatrixScaling(1.5f, 2.0f, 1.0f);
  1299.     UINT objCBIndex = 5;
  1300.     for(int i = 0; i < 5; ++i)
  1301.     {
  1302.         auto leftCylRitem = std::make_unique<RenderItem>();
  1303.         auto rightCylRitem = std::make_unique<RenderItem>();
  1304.         auto leftSphereRitem = std::make_unique<RenderItem>();
  1305.         auto rightSphereRitem = std::make_unique<RenderItem>();
  1306.  
  1307.         XMMATRIX leftCylWorld = XMMatrixTranslation(-5.0f, 1.5f, -10.0f + i*5.0f);
  1308.         XMMATRIX rightCylWorld = XMMatrixTranslation(+5.0f, 1.5f, -10.0f + i*5.0f);
  1309.  
  1310.         XMMATRIX leftSphereWorld = XMMatrixTranslation(-5.0f, 3.5f, -10.0f + i*5.0f);
  1311.         XMMATRIX rightSphereWorld = XMMatrixTranslation(+5.0f, 3.5f, -10.0f + i*5.0f);
  1312.  
  1313.         XMStoreFloat4x4(&leftCylRitem->World, rightCylWorld);
  1314.         XMStoreFloat4x4(&leftCylRitem->TexTransform, brickTexTransform);
  1315.         leftCylRitem->ObjCBIndex = objCBIndex++;
  1316.         leftCylRitem->Mat = mMaterials["bricks0"].get();
  1317.         leftCylRitem->Geo = mGeometries["shapeGeo"].get();
  1318.         leftCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1319.         leftCylRitem->IndexCount = leftCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  1320.         leftCylRitem->StartIndexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  1321.         leftCylRitem->BaseVertexLocation = leftCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  1322.  
  1323.         XMStoreFloat4x4(&rightCylRitem->World, leftCylWorld);
  1324.         XMStoreFloat4x4(&rightCylRitem->TexTransform, brickTexTransform);
  1325.         rightCylRitem->ObjCBIndex = objCBIndex++;
  1326.         rightCylRitem->Mat = mMaterials["bricks0"].get();
  1327.         rightCylRitem->Geo = mGeometries["shapeGeo"].get();
  1328.         rightCylRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1329.         rightCylRitem->IndexCount = rightCylRitem->Geo->DrawArgs["cylinder"].IndexCount;
  1330.         rightCylRitem->StartIndexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].StartIndexLocation;
  1331.         rightCylRitem->BaseVertexLocation = rightCylRitem->Geo->DrawArgs["cylinder"].BaseVertexLocation;
  1332.  
  1333.         XMStoreFloat4x4(&leftSphereRitem->World, leftSphereWorld);
  1334.         leftSphereRitem->TexTransform = MathHelper::Identity4x4();
  1335.         leftSphereRitem->ObjCBIndex = objCBIndex++;
  1336.         leftSphereRitem->Mat = mMaterials["mirror0"].get();
  1337.         leftSphereRitem->Geo = mGeometries["shapeGeo"].get();
  1338.         leftSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1339.         leftSphereRitem->IndexCount = leftSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  1340.         leftSphereRitem->StartIndexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1341.         leftSphereRitem->BaseVertexLocation = leftSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1342.  
  1343.         XMStoreFloat4x4(&rightSphereRitem->World, rightSphereWorld);
  1344.         rightSphereRitem->TexTransform = MathHelper::Identity4x4();
  1345.         rightSphereRitem->ObjCBIndex = objCBIndex++;
  1346.         rightSphereRitem->Mat = mMaterials["mirror0"].get();
  1347.         rightSphereRitem->Geo = mGeometries["shapeGeo"].get();
  1348.         rightSphereRitem->PrimitiveType = D3D11_PRIMITIVE_TOPOLOGY_TRIANGLELIST;
  1349.         rightSphereRitem->IndexCount = rightSphereRitem->Geo->DrawArgs["sphere"].IndexCount;
  1350.         rightSphereRitem->StartIndexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].StartIndexLocation;
  1351.         rightSphereRitem->BaseVertexLocation = rightSphereRitem->Geo->DrawArgs["sphere"].BaseVertexLocation;
  1352.  
  1353.         mRitemLayer[(int)RenderLayer::Opaque].push_back(leftCylRitem.get());
  1354.         mRitemLayer[(int)RenderLayer::Opaque].push_back(rightCylRitem.get());
  1355.         mRitemLayer[(int)RenderLayer::Opaque].push_back(leftSphereRitem.get());
  1356.         mRitemLayer[(int)RenderLayer::Opaque].push_back(rightSphereRitem.get());
  1357.  
  1358.         mAllRitems.push_back(std::move(leftCylRitem));
  1359.         mAllRitems.push_back(std::move(rightCylRitem));
  1360.         mAllRitems.push_back(std::move(leftSphereRitem));
  1361.         mAllRitems.push_back(std::move(rightSphereRitem));
  1362.     }
  1363. }
  1364.  
  1365. void ShadowMapApp::DrawRenderItems(ID3D12GraphicsCommandList* cmdList, const std::vector<RenderItem*>& ritems)
  1366. {
  1367.     UINT objCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(ObjectConstants));
  1368.  
  1369.     auto objectCB = mCurrFrameResource->ObjectCB->Resource();
  1370.  
  1371.     // For each render item...
  1372.     for(size_t i = 0; i < ritems.size(); ++i)
  1373.     {
  1374.         auto ri = ritems[i];
  1375.  
  1376.         cmdList->IASetVertexBuffers(0, 1, &ri->Geo->VertexBufferView());
  1377.         cmdList->IASetIndexBuffer(&ri->Geo->IndexBufferView());
  1378.         cmdList->IASetPrimitiveTopology(ri->PrimitiveType);
  1379.  
  1380.         D3D12_GPU_VIRTUAL_ADDRESS objCBAddress = objectCB->GetGPUVirtualAddress() + ri->ObjCBIndex*objCBByteSize;
  1381.  
  1382.         cmdList->SetGraphicsRootConstantBufferView(0, objCBAddress);
  1383.  
  1384.         cmdList->DrawIndexedInstanced(ri->IndexCount, 1, ri->StartIndexLocation, ri->BaseVertexLocation, 0);
  1385.     }
  1386. }
  1387.  
  1388. void ShadowMapApp::DrawSceneToShadowMap()
  1389. {
  1390.     mCommandList->RSSetViewports(1, &mShadowMap->Viewport());
  1391.     mCommandList->RSSetScissorRects(1, &mShadowMap->ScissorRect());
  1392.  
  1393.     // Change to DEPTH_WRITE.
  1394.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mShadowMap->Resource(),
  1395.         D3D12_RESOURCE_STATE_GENERIC_READ, D3D12_RESOURCE_STATE_DEPTH_WRITE));
  1396.  
  1397.     UINT passCBByteSize = d3dUtil::CalcConstantBufferByteSize(sizeof(PassConstants));
  1398.  
  1399.     // Clear the back buffer and depth buffer.
  1400.     mCommandList->ClearDepthStencilView(mShadowMap->Dsv(), 
  1401.         D3D12_CLEAR_FLAG_DEPTH | D3D12_CLEAR_FLAG_STENCIL, 1.0f, 0, 0, nullptr);
  1402.  
  1403.     // Set null render target because we are only going to draw to
  1404.     // depth buffer.  Setting a null render target will disable color writes.
  1405.     // Note the active PSO also must specify a render target count of 0.
  1406.     mCommandList->OMSetRenderTargets(0, nullptr, false, &mShadowMap->Dsv());
  1407.  
  1408.     // Bind the pass constant buffer for the shadow map pass.
  1409.     auto passCB = mCurrFrameResource->PassCB->Resource();
  1410.     D3D12_GPU_VIRTUAL_ADDRESS passCBAddress = passCB->GetGPUVirtualAddress() + 1*passCBByteSize;
  1411.     mCommandList->SetGraphicsRootConstantBufferView(1, passCBAddress);
  1412.  
  1413.     mCommandList->SetPipelineState(mPSOs["shadow_opaque"].Get());
  1414.  
  1415.     DrawRenderItems(mCommandList.Get(), mRitemLayer[(int)RenderLayer::Opaque]);
  1416.  
  1417.     // Change back to GENERIC_READ so we can read the texture in a shader.
  1418.     mCommandList->ResourceBarrier(1, &CD3DX12_RESOURCE_BARRIER::Transition(mShadowMap->Resource(),
  1419.         D3D12_RESOURCE_STATE_DEPTH_WRITE, D3D12_RESOURCE_STATE_GENERIC_READ));
  1420. }
  1421.  
  1422. std::array<const CD3DX12_STATIC_SAMPLER_DESC, 7> ShadowMapApp::GetStaticSamplers()
  1423. {
  1424.     // Applications usually only need a handful of samplers.  So just define them all up front
  1425.     // and keep them available as part of the root signature.  
  1426.  
  1427.     const CD3DX12_STATIC_SAMPLER_DESC pointWrap(
  1428.         0, // shaderRegister
  1429.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1430.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1431.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1432.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1433.  
  1434.     const CD3DX12_STATIC_SAMPLER_DESC pointClamp(
  1435.         1, // shaderRegister
  1436.         D3D12_FILTER_MIN_MAG_MIP_POINT, // filter
  1437.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1438.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1439.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1440.  
  1441.     const CD3DX12_STATIC_SAMPLER_DESC linearWrap(
  1442.         2, // shaderRegister
  1443.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1444.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1445.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1446.         D3D12_TEXTURE_ADDRESS_MODE_WRAP); // addressW
  1447.  
  1448.     const CD3DX12_STATIC_SAMPLER_DESC linearClamp(
  1449.         3, // shaderRegister
  1450.         D3D12_FILTER_MIN_MAG_MIP_LINEAR, // filter
  1451.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1452.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1453.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP); // addressW
  1454.  
  1455.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicWrap(
  1456.         4, // shaderRegister
  1457.         D3D12_FILTER_ANISOTROPIC, // filter
  1458.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressU
  1459.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressV
  1460.         D3D12_TEXTURE_ADDRESS_MODE_WRAP,  // addressW
  1461.         0.0f,                             // mipLODBias
  1462.         8);                               // maxAnisotropy
  1463.  
  1464.     const CD3DX12_STATIC_SAMPLER_DESC anisotropicClamp(
  1465.         5, // shaderRegister
  1466.         D3D12_FILTER_ANISOTROPIC, // filter
  1467.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressU
  1468.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressV
  1469.         D3D12_TEXTURE_ADDRESS_MODE_CLAMP,  // addressW
  1470.         0.0f,                              // mipLODBias
  1471.         8);                                // maxAnisotropy
  1472.  
  1473.     const CD3DX12_STATIC_SAMPLER_DESC shadow(
  1474.         6, // shaderRegister
  1475.         D3D12_FILTER_COMPARISON_MIN_MAG_LINEAR_MIP_POINT, // filter
  1476.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressU
  1477.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressV
  1478.         D3D12_TEXTURE_ADDRESS_MODE_BORDER,  // addressW
  1479.         0.0f,                               // mipLODBias
  1480.         16,                                 // maxAnisotropy
  1481.         D3D12_COMPARISON_FUNC_LESS_EQUAL,
  1482.         D3D12_STATIC_BORDER_COLOR_OPAQUE_BLACK);
  1483.  
  1484.     return { 
  1485.         pointWrap, pointClamp,
  1486.         linearWrap, linearClamp, 
  1487.         anisotropicWrap, anisotropicClamp,
  1488.         shadow 
  1489.     };
  1490. }
  1491.  
  1492.